package com.semlab.client.fwk.ap;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import com.google.gwt.activity.shared.ActivityManager;
import com.google.gwt.activity.shared.ActivityMapper;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.inject.Inject;
import com.semlab.client.fwk.Utils;

public class DefaultActivityRegistry implements ActivityRegistry {

	private static final Logger log = Logger.getLogger(DefaultActivityRegistry.class.getName());

	private EventBus eventBus;
	protected ApplicationMapping appMapping;

	@Inject
	public DefaultActivityRegistry(EventBus eventBus) {
		log.fine(":: creating manager");
		this.eventBus = eventBus;
		this.appMapping = new ApplicationMapping();
	}
	
	/**
	 * Ties {@link ContainerMapping} for a display (div) {@link ContainerMapping#setWidget(AcceptsOneWidget)}
	 */
	@Override
	public void registerContainer(String displayId, AcceptsOneWidget display) {
		if (displayId == null || display == null) {
			throw new IllegalArgumentException("Container and container id must not be null");
		}
		String theContainerId = displayId.trim();
		if (!Utils.hasLength(theContainerId)) {
			throw new IllegalArgumentException("Container id must not be empty");
		}
		appMapping.registerContainer(theContainerId, display);
	}

	/**
	 * Go trough all containers {@link ContainerMapping} and bind activities and places ({@link MappingsEntry}) 
	 * to mapper {@link CompositeActivityMapper} and manager {@link CustomActivityManager} for that container
	 */
	public void process() {
//		log.fine("proces Mappings " + appMapping);
		ArrayList<ContainerMapping> containers = appMapping.getContainers();
		for (ContainerMapping containerMapping : containers) {
			log.fine("processing...");
			List<MappingsEntry> activities = containerMapping.getPlaceMappings();
			if (activities == null || activities.size() == 0) {
				log.fine("there no activities for display [" + containerMapping.getId() + "]");
				continue;
			}
//			log.fine("creating activity manager for display [" + containerMapping.getId() + "] with [" + activities.size() + "] activities");
			CompositeActivityMapper activityMapper = new CompositeActivityMapper(activities);
//			final CustomActivityManager masterActivityManager = new CustomActivityManager(containerMapping.getId(), activityMapper, eventBus);
			final ActivityManager masterActivityManager = new ActivityManager(activityMapper, eventBus);
			masterActivityManager.setDisplay(containerMapping.getContainerWidget());
			containerMapping.setActivityManager(masterActivityManager);
		}
		appMapping.clearMappingsForUpdate();
	}

	/**
	 * Ties {@link MappingsEntry} for a container {@link ContainerMapping#addMappingEntry(MappingsEntry)}
	 */
	@Override
	public void registerActivity(MappingsEntry mappingEntry) {
		log.fine("register " + mappingEntry);
		if (mappingEntry == null)
			return;
		
		Place place = mappingEntry.getPlace();

		ArrayList<Place> parPlaces = place.getParameterPlaces();
		
//		//tie place to a parent place activity
//		for (Place parPlace : parPlaces) {
//			ActivityMapper map = appMapping.getActivityMapperForPlace(parPlace.getContainerId(), parPlace);
//			MappingsEntry newMappingEntry = new MappingsEntry(place, map);
//
//			appMapping.registerMapping(parPlace.getContainerId(), newMappingEntry);
//			if(map == null){
//				newMappingEntry.setParentPlace(parPlace);
//				//handler not present, update this mapping entry when it comes around
//				appMapping.scheduleMappingForUpdate(newMappingEntry);
//			}
//		}
		
		// check if someone is waiting for this handler 
		appMapping.updateMappings(mappingEntry);
		appMapping.registerMapping(place.getContainerId(), mappingEntry);
	}
	

	@Override
	public void registerNestedPlace(Place place, Place parPlace) {
		ActivityMapper map = appMapping.getActivityMapperForPlace(parPlace.getContainerId(), parPlace);
		MappingsEntry newMappingEntry = new MappingsEntry(place, map);

		appMapping.registerMapping(parPlace.getContainerId(), newMappingEntry);
		if(map == null){
			newMappingEntry.setParentPlace(parPlace);
			//handler not present, update this mapping entry when it comes around
			appMapping.scheduleMappingForUpdate(newMappingEntry);
		}
	}
	
}
